﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace NaiveBayesClassifier
{
    public class CBaseInstance : IInstance
    {
        protected IConcept concept;
        protected CStringAttribute[] attributes;

        public CBaseInstance(IConcept concept, CStringAttribute[] attributes)
        {
            this.concept = concept;
            this.attributes = attributes;
        }

        public static CBaseInstance CreateInstance(string conceptName,
            string[] attributeNames, string[] attributeValues)
        {
            int n = attributeNames.Length;
            CStringAttribute[] attributes = new CStringAttribute[n];
            for (int i = 0; i < n; ++i)
            {
                attributes[i] = new CStringAttribute(attributeNames[i], attributeValues[i]);
            }
            IConcept concept = new CBaseConcept(conceptName);
            return new CBaseInstance(concept, attributes);
        }

        public static CBaseInstance[] LoadFromFile(string fileName, char[] separator)
        {
            Stream inputStream = File.OpenRead(fileName);
            StreamReader sr = new StreamReader(inputStream);
            return LoadFromFile(sr, separator);
        }

        public static CBaseInstance[] LoadFromFile(StreamReader sr, char[] separator)
        {
            List<CBaseInstance> baseInstances = new List<CBaseInstance>();
            string line;

            try
            {
                // đọc dòng đầu tiên: tên các thuộc tính
                line = sr.ReadLine();
                string[] titles = line.Split(separator, StringSplitOptions.RemoveEmptyEntries);
                int n = titles.Length;

                do
                {
                    line = sr.ReadLine();
                    if (line == null || line.Length == 0)
                        break;

                    string[] data = line.Split(separator, StringSplitOptions.RemoveEmptyEntries);
                    CStringAttribute[] attributes = new CStringAttribute[n - 1];
                    for (int i = 0; i < n - 1; ++i)
                        attributes[i] = new CStringAttribute(titles[i], data[i]);
                    baseInstances.Add(new CBaseInstance(new CBaseConcept(data[n - 1]), attributes));
                } while (true);

                return baseInstances.ToArray();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return null;
            }
        }

        #region Getter and Setter
        public IAttribute[] GetAttributes()
        {
            return attributes;
        }

        public IAttribute GetAttributeByName(string attributeName)
        {
            IAttribute matched = null;
            foreach (CStringAttribute a in attributes)
            {
                if (a.GetName().Equals(attributeName, StringComparison.OrdinalIgnoreCase))
                {
                    matched = a;
                    break;
                }
            }
            return matched;
        }

        public CStringAttribute GetAttributeAt(int index)
        {
            return attributes[index];
        }

        public IConcept GetConcept()
        {
            return concept;
        }

        public void SetConcept(IConcept concept)
        {
            this.concept = concept;
        }
        #endregion

        public override bool Equals(object obj)
        {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (!(obj is CBaseInstance))
                return false;

            CBaseInstance other = (CBaseInstance)obj;

            if (concept == null)
            {
                if (other.concept != null)
                    return false;
            }
            else if (!concept.Equals(other.concept))
                return false;

            for (int i = 0; i < attributes.Length; ++i)
                if (attributes[i] == null)
                {
                    if (other.attributes[i] != null)
                        return false;
                }
                else if (!attributes[i].Equals(other.attributes[i]))
                    return false;

            return true;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }
}
